home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Deutsche Edition 1
/
Deutsche Edition 1.iso
/
amok
/
081-090
/
amok87
/
muchmore
/
src
/
muchmore.mod
next >
Wrap
Text File
|
1993-11-04
|
86KB
|
2,639 lines
(*---------------------------------------------------------------------------
:Program. MuchMore.mod
:Author. Fridtjof Siebert
:Address. Nobileweg 67, D-7000 Stuttgart 40
:Shortcut. [fbs]
:Copyright. Freeware
:Language. Oberon-2
:Translator. Amiga Oberon Compiler v3.01
:History. V1.0 summer-88: First very slow internal version [fbs]
:History. V1.1 24-Sep-88: First published version [fbs]
:History. V1.2 26-Nov-88: Now displays Filelength & Percentage [fbs]
:History. 27-Nov-88: Mouse can be used instead of Space / BackSpace[fbs]
:History. V1.3 29-Apr-89: Strong increase in speed, removed WarpText [fbs]
:History. 29-Apr-89: Now supports Numeric Keys (Home,PgUp etc.) [fbs]
:History. 29-Apr-89: Now opens Screen as big as gfx.normalDisplay [fbs]
:History. V1.4 29/30-Apr-89: Asynchronus loading / displaying. Very nice[fbs]
:History. 30-Apr-89, 00:33: Removed bugs in Filelength & L-Command [fbs]
:History. 30-Apr-89, 02:21: Added Find-Command [fbs]
:History. 30-Apr-89, 10:30: Scrolling stops when window is inactive[fbs]
:History. 01-May-89: Allocates no more unneeded memory for text [fbs]
:History. 07-May-89: Allocates even less memory now [fbs]
:History. 14-May-89: Removed deadlock-bug with Find-Window [fbs]
:History. V1.5 25-May-89: Added print feature [fbs]
:History. 25-May-89: Removed all imports (apart from Arts) [fbs]
:History. 26-May-89: inspired by J. Kupfer, I added nk 5 to quit [fbs]
:History. 26-May-89: Now handle BS correctly [fbs]
:History. V1.6 02-Jul-89: Now supports several fontstyles and colors [fbs]
:History. V1.7 03-Jul-89: Is again as fast as it was with 2 colors [fbs]
:History. 03-Jul-89: Now no more crashes when quitting while print [fbs]
:History. 07-Jul-89: removed bug with texts of length 0 [fbs]
:History. V1.8 10-Jul-89: small bug in find-command removed [fbs]
:History. 10-Jul-89: now found strings are highlighted [fbs]
:History. 14-Jul-89: nk0 to display fileinfo [fbs]
:History. V2.0 06-Aug-89: Ported this to OBERON [fbs]
:History. 06-Aug-89: Added ARP-FileRequester [fbs]
:History. 07-Aug-89: Added L - (load new file) Command [fbs]
:History. V2.1 03-Sep-89: no more gurus if an r/w error occures [fbs]
:History. 03-Sep-89: MM used to execute CSI-Codes backwards. fixed [fbs]
:History. 03-Sep-89: ping / pong with Shift+Fn / Fn [fbs]
:History. 03-Sep-89: new command: goto [fbs]
:History. V2.2 05-Sep-89: will run with any keymapping now [fbs]
:History. V2.3 17-Sep-89: New command: sleep & Pop-Up feature [fbs]
:History. 17-Sep-89: "MuchMore -s" will go to sleep immediately [fbs]
:History. 17-Sep-89: Interprets <CSI>m as <CSI>0m now [fbs]
:History. V2.4 17-Sep-89: New command: write block "w" [fbs]
:History. 17-Sep-89: rewritten argument parser to allow quotes [fbs]
:History. V2.5 18-Sep-89: now uses the 8x8 font set with SetFont [fbs]
:History. 19-Sep-89: no more scatters memory. Allocates 4K Chunks [fbs]
:History. V2.6 26-Jun-90: Made MuchMore reentrant [fbs]
:History. 26-Jun-90: Opens 1-Plane Screen if memory is rare [fbs]
:History. 26-Jun-90: Asynchronus fast scrolling with Ctrl-Up/Down [fbs]
:History. 26-Jun-90: Now supports interlaced screens [fbs]
:History. 08-Aug-90: CLI-Option '-l' to toggle interlaced mode [fbs]
:History. V2.7 09-Aug-90: no more RethinkDisplay()s,looks good with 2.0 [fbs]
:History. 10-Aug-90: Supports Kick2.0 ASL-FileRequester [fbs]
:History. V2.8 26-Dez-90: Leaves space between lines on interlaced scrns[fbs]
:History. V3.0 04-Jul-91: Supports any non-proportional font now [fbs]
:History. 04-Jul-91: no more supports '-s' (sleep), was rarely used[fbs]
:History. 04-Jul-91: new Options -f<font> and -s<size> for font [fbs]
:History. 09-Nov-91: Find works w/ dmouse (window may get inactive)[fbs]
:History. V3.1 04-Sep-92: Uses Screenmode of Workbench screen [fbs]
:History. V3.2 02-Nov-92: Supports non-scrollable screens [fbs]
:History. 02-Nov-92: Complete redraw doesn't scroll anymore [fbs]
:History. V3.2.1 24-Dec-92: XPK Support (Chr. Stiens)
:History. 24-Dec-92: New option -p for Password (Chr. Stiens)
:History. 24-Dec-92: New option -e for Extra Spacing (Chr. Stiens)
:History. 24-Dec-92: New option -c for Screen Colors (Chr. Stiens)
:History. 24-Dec-92: Tooltypes (Chr. Stiens)
:History. V3.2.2 08-Jan-93: Doesn't use MyMakeScreen() no more (Chr. Stiens)
:History. V3.2.3 08-Feb-93: Now closes Console Device (Chr. Stiens)
:History. 08-Feb-93: Non-Scroll Mode didn't work always (Chr. Stiens)
:History. 10-Feb-93: ScreenMode Requester (Chr. Stiens)
:History. 10-Feb-93: New Option -s for Scroll Mode (Chr. Stiens)
:History. 10-Feb-93: Busy Pointer (Chr. Stiens)
:History. 14-Feb-93: Now evals Tooltypes also on CLI start (Chr. Stiens)
:History. V3.2.4 15-Feb-93: Clears Idcmp while Busy (Chr. Stiens)
:History. 15-Feb-93: Bugs in GetString fixed (Chr. Stiens)
:History. 19-Feb-93: More Scrollmodes (Chr. Stiens)
:History. 20-Feb-93: Bug in Type() fixed (Chr. Stiens)
:History. V3.2.5 08-Mar-93: Removed Asynch Scrolling (Chr. Stiens)
:History. 08-Mar-93: New Option -t for Taskpri (Chr. Stiens)
:History. 10-Mar-93: Now uses Dos.ReadArgs if KS 2.04 (Chr. Stiens)
:History. V3.2.6 19-Mar-93: scrollmode 3 now also scrolls soft (Chr. Stiens)
:History. 19-Mar-93: New Option -o for one plane (Chr. Stiens)
:History. 19-Mar-93: New Option -a for tab width (Chr. Stiens)
:History. 19-Mar-93: Removed QText (Chr. Stiens)
:History. 21-Mar-93: Opens screen with full overscan width (Chr. Stiens)
:History. 22-Mar-93: Filename can be on any pos at KS1.3 (Chr. Stiens)
:History. 27-Mar-93: New Option N=NOOSCAN (Chr. Stiens)
:History. V3.2.7 07-Apr-93: Dont pokes to bitmap no more (Chr. Stiens)
:Contents. A Soft-Scrolling ASCII-File Printer.
:Remark. Compile: 'Oberon -[svbcrntz]dma MuchMore'
:Remark. Link: 'OLink -dma MuchMore'
---------------------------------------------------------------------------*)
MODULE MuchMore; (* $StackChk- *)
IMPORT d := Dos,
e := Exec,
g := Graphics,
gt := GadTools,
I := Intuition,
ie := InputEvent,
str:= Strings,
u := Utility,
ol := OberonLib,
SYS:= SYSTEM;
(*-------------------------------------------------------------------------*)
CONST
oom = "Out of memory!";
cos = "Can't open screen!";
cow = "Can't open window!";
cof = "Can't open file!";
usage = "Usage: MuchMore [-a#|-c#{,#}|-e#|-f<name>/#|-l|-o|-p<name>|-s#|-t#|file]\n"
"\ta = tab width\n"
"\tc = colors\n"
"\te = extra spacing\n"
"\tf = font/size\n"
"\tl = toggle lace\n"
"\to = one plane\n"
"\tp = password\n"
"\ts = scroll mode\n"
"\tt = toolpri";
rwerr = "Read/Write Error";
noarp = "Need arp for FileReq";
conerr = "Console problem";
MuchText = "MuchMore V3.2.7 © 1993 AMOK\o$VER: muchmore 3.27 (7.4.93)";
w = TRUE;
f = FALSE;
MaxLen = 256;
MyIdcmp = LONGSET{I.inactiveWindow,I.activeWindow,I.rawKey,I.mouseButtons};
(* Control codes: *)
plain = CHR(17);
italic = CHR(18);
bold = CHR(19);
boldit = CHR(20);
ulineon = CHR(21);
ulineoff = CHR(22);
Italic = 0;
Bold = 1;
Ulin = 2;
Inv = 3;
saInterleaved = I.saDummy + 00022H;
TYPE
String = e.STRING;
StringPtr = e.STRPTR;
CharPtr = UNTRACED POINTER TO CHAR;
TextLinePtr = UNTRACED POINTER TO TextLine;
TextLine = STRUCT
prev,
next : TextLinePtr;
len : INTEGER;
size : INTEGER;
text : String;
END;
TYPE
FileRequesterPtr = UNTRACED POINTER TO FileRequester;
FileRequester = STRUCT
hail : StringPtr;
ddef : StringPtr;
ddir : StringPtr;
wind : I.WindowPtr;
funcFlags : SHORTSET;
flags2 : SHORTSET;
function : PROCEDURE;
reserved2 : LONGINT;
END;
WBStartupPtr = UNTRACED POINTER TO STRUCT (message : e.Message)
process : d.ProcessId;
segment : e.BPTR;
numArgs : LONGINT;
toolWindow : StringPtr;
argList : UNTRACED POINTER TO ARRAY 256 OF STRUCT
lock : d.FileLockPtr;
name : StringPtr;
END;
END;
DiskObjectPtr = UNTRACED POINTER TO STRUCT
magic : INTEGER;
version : INTEGER;
gadget : I.Gadget;
type : SHORTINT;
defaultTool: StringPtr;
toolTypes : e.APTR;
currentX : LONGINT;
currentY : LONGINT;
drawerData : e.APTR;
toolWindow : StringPtr;
stackSize : LONGINT;
END;
LongPtr = UNTRACED POINTER TO LONGINT;
Args = STRUCT
a : LongPtr;
c : StringPtr;
d : StringPtr;
e : LongPtr;
f : StringPtr;
n : StringPtr;
o : StringPtr;
p : StringPtr;
s : LongPtr;
t : LongPtr;
file : StringPtr;
END;
VAR
pub: I.ScreenPtr; (* default public screen *)
Screen: I.ScreenPtr; (* Screen that contains the Text *)
rp: g.RastPortPtr; (* Screen's RastPort *)
id: LONGINT; (* Display ID *)
BM: g.BitMapPtr; (* Screen's BitMap *)
Window: I.WindowPtr; (* My window *)
win: I.WindowPtr; (* window for Find & Goto *)
MyFile: d.FileHandlePtr; (* For loading Textfile *)
MyAttr: g.TextAttr; (* The selected Font attributes *)
MyFont: g.TextFontPtr; (* The selected Font *)
FontName: String; (* My Font Name or "" *)
FontSize: INTEGER; (* My Font Size *)
FirstLine: TextLinePtr; (* the topmost Line *)
TopLine: TextLinePtr; (* the topmost Line *)
BottomLine: TextLinePtr; (* Last Line displayed on Screen *)
LoadLine: TextLinePtr; (* currently loaded Line *)
LastLine: TextLinePtr; (* Last element of LineList *)
Name,OldName: String; (* Text's Name *)
option: String; (* CLI Option *)
taskpri,oldpri: SHORTINT; (* Muchmore's Task Priority *)
Pens: String; (* Screen colors *)
Cols: ARRAY 4 OF INTEGER; (* Color array for LoadRGB4 *)
icon: DiskObjectPtr; (* .info *)
nameptr: StringPtr; (* String Pointer *)
chptr: CharPtr; (* Char Pointer *)
PStr: String; (* The command for Dos.Execute *)
Buffer: ARRAY 512 OF CHAR; (* Buffer for Reading *)
RQPos: LONGINT; (* Position within ReadBuffer *)
RQLen: LONGINT; (* Number of CHARs in Buffer *)
scrollmode: INTEGER; (* 0=MakeScreen/MrgCop 1=ScrollVPort *)
NumLines: INTEGER; (* Number of Lines on Screen *)
fontWidth,fontHeight: INTEGER; (* Font size *)
fontBaseLine: INTEGER; (* Font base line *)
spacing: INTEGER; (* Extra Line Spacing *)
NumColumns: INTEGER; (* Number of Columns on Screen *)
PageSize: LONGINT; (* fontHeight*NumLines*NumColumns *)
PageHeight: INTEGER; (* fontHeight*NumLines *)
LineSize: LONGINT; (* fontHeight*NumColumns *)
AnzLines: LONGINT; (* Length of Text in Lines *)
MyLock,OldDir: d.FileLockPtr; (* To Examine and Load File *)
oldcd: d.FileLockPtr; (* To save old CD *)
FileInfo: d.FileInfoBlock; (* to get File's length *)
FileLength,TextLength: LONGINT;(* Length of File and Displayed Text *)
ScreenPos: INTEGER; (* actual position within bitmap *)
ShowTask: e.Task; (* the task that displays the text *)
ShowStack: ARRAY 1024 OF LONGINT; (* it's stack *)
ShowTaskRunning: BOOLEAN; (* is Showtask activated? *)
SignalNewData: BOOLEAN; (* Signal when new data is loaded *)
SignalAllRead: BOOLEAN; (* send signal at end of text *)
Done: BOOLEAN; (* Quit *)
print: BOOLEAN; (* print text *)
NewText: BOOLEAN; (* load new text *)
Info: BOOLEAN; (* is info currently displayed ? *)
modeReq: BOOLEAN; (* Show Display Mode Requester? *)
onePlane: BOOLEAN; (* Only one Bitplane? *)
Scroll: BOOLEAN; (* scrolling or waiting? *)
Fast: BOOLEAN; (* scrollquick? *)
Sync: BOOLEAN; (* scroll very quick? *)
lace,oldLace: BOOLEAN; (* use interlaced screen? *)
Decrunched: BOOLEAN; (* Is file decrunched? *)
Scrollable: BOOLEAN; (* is screen able to scroll? *)
noOscan: BOOLEAN; (* Open Text-overscan Screen? *)
overscanTag: LONGINT; (* overscan tag *)
mySigBit: INTEGER; (* My SignalBit *)
mySig: LONGSET; (* My SignalSet = LONGSET{mySigBit} *)
Me: d.ProcessPtr; (* my main task *)
MyMsgPtr: I.IntuiMessagePtr; (* for receiving Messages *)
i,j: INTEGER; (* count *)
frame: INTEGER; (* Frame Count *)
in,out: d.FileHandlePtr; (* i/o for TYPE xxx TO PRT: *)
fg,bg: INTEGER; (* Text colors *)
style: SHORTSET; (* Text style *)
CommLine: UNTRACED POINTER TO ARRAY 1000 OF CHAR;(* The CLI-commands*)
tabw: INTEGER; (* Tabulator width *)
rd: d.RDArgsPtr; (* For ReadArgs *)
args: Args; (* My CLI Args *)
ArgPtr: StringPtr; (* to get WBArg *)
wbm: WBStartupPtr; (* WBenchMessage *)
ri: g.RasInfoPtr; (* Screen's ViewPort's RasInfo *)
NuScreen: I.NewScreen; (* to open screen *)
dims: g.DimensionInfo; (* Dims for KS2.0 *)
disp: g.DisplayInfo; (* DisplayInfo for KS2.0 *)
NuWindow: I.NewWindow; (* to open window *)
Prefs: I.Preferences; (* Preferences (need wbLace) *)
StrGadget: I.Gadget; (* Gadget for Find-Command *)
StrInfo: I.StringInfo; (* its special info *)
arp: e.LibraryPtr; (* ArpBase *)
asl: e.LibraryPtr; (* ASL-librarybase *)
diskFontBase : e.LibraryPtr; (* DiskFont-LibraryBase *)
xpk: e.LibraryPtr; (* XpkMaster-Librarybase *)
iconBase: e.LibraryPtr; (* Icon-Librarybase *)
body,text,ok: I.IntuiText; (* IntuiTexts for AutoRequest *)
FR: FileRequester; (* The Requester *)
Filename: String; (* The Filename (without path) *)
Dirname: String; (* its path *)
Pattern: ARRAY 80 OF CHAR; (* The pattern for Filerequester *)
Password: String; (* Password for encrypted texts *)
NewDisp: BOOLEAN; (* need to rebuild Display ? *)
TextMarkers: ARRAY 10 OF TextLinePtr; (* Marked Positions in text *)
FindLine: TextLinePtr; (* Last found line *)
KeyMap: ARRAY 50H OF CHAR; (* console's KeyMap *)
wreq: e.IOStdReq; (* Console IO-Request *)
console: e.DevicePtr; (* the console.device *)
ievent: ie.InputEvent; (* InputEvent to convert keycodes *)
WriteName: String; (* File to write Block *)
savefrom,savesize: LONGINT; (* How much to save? *)
save: BOOLEAN; (* save block *)
buffer: UNTRACED POINTER TO LONGINT; (* buffer to save file *)
c: CHAR; (* \ used by GetTextLine(); *)
le: INTEGER; (* / global for speed *)
(*------ Memory: ------*)
CONST ChunkSize = 16384; (* size of allocated chunks *)
TYPE
MemChunkPtr = UNTRACED POINTER TO MemChunk; (* chunklist *)
MemChunk = STRUCT
prev: MemChunkPtr; (* link *)
data: ARRAY ChunkSize OF SYS.BYTE; (* ChunkSize Bytes of memory *)
END;
VAR
MemIndex: INTEGER; (* index in current Chunk *)
CurChunk: MemChunkPtr; (* current chunk *)
(*-------------------------------------------------------------------------*)
(*------ Console Procedure: ------*)
PROCEDURE RawKeyConvert{console,-48}(events{8}:ie.InputEventPtr;
buffer{9}:LONGINT;
length{1}:LONGINT;
keyMap{10}:LONGINT);
(*-------------------------------------------------------------------------*)
(*------ DiskFont Procedure: ------*)
PROCEDURE OpenDiskFont*{diskFontBase,-30}(VAR textAttr{8}: g.TextAttr): g.TextFontPtr;
(*-------------------------------------------------------------------------*)
(*------ Icon Procedures: ------*)
PROCEDURE GetDiskObject {iconBase,- 78}(name{8} : ARRAY OF CHAR): DiskObjectPtr;
PROCEDURE FreeDiskObject{iconBase,- 90}(diskobj{8} : DiskObjectPtr);
PROCEDURE FindToolType {iconBase,- 96}(toolTypes{8} : e.APTR;
typeName{9} : ARRAY OF CHAR): StringPtr;
PROCEDURE MatchToolValue{iconBase,-102}(typeString{8} : ARRAY OF CHAR;
val{9} : ARRAY OF CHAR): BOOLEAN;
(*-------------------------------------------------------------------------*)
PROCEDURE Append(VAR s1: String; s2: StringPtr);
(* appends s2 to s1 *)
VAR p,q: INTEGER;
BEGIN
p := SHORT(str.Length(s1)); q := 0;
WHILE (p<SIZE(s1)) & (s2^[q]#0X) & (p<NumColumns) DO
s1[p] := s2^[q]; INC(p); INC(q)
END;
IF p<SIZE(s1) THEN s1[p] := 0X END;
END Append;
(*----------------------------- Requester: ------------------------------*)
PROCEDURE Request(Text: ARRAY OF CHAR); (* $CopyArrays- *)
VAR
out: d.FileHandlePtr;
c: CHAR;
BEGIN
IF ol.wbStarted THEN
body.frontPen := 0; body.backPen := 1; body.drawMode := g.jam2;
body.leftEdge := 12; body.topEdge := 8;
text := body; ok := body;
body.iText := SYS.ADR(MuchText);
body.nextText := SYS.ADR(text);
text.iText := SYS.ADR(Text); text.topEdge := 22;
ok.leftEdge := 6; ok.topEdge := 3; ok.iText := SYS.ADR(" OK ");
SYS.SETREG(0,I.AutoRequest(NIL,SYS.ADR(body),NIL,SYS.ADR(ok),LONGSET{I.rawKey},LONGSET{},320,65));
ELSE
out := d.Output();
SYS.SETREG(0,d.Write(out,Text,str.Length(Text)));
c := 0AX;
SYS.SETREG(0,d.Write(out,c,1));
END;
HALT(0);
END Request;
PROCEDURE OutOfMemHandler;
CONST ES = I.EasyStruct(SIZE(I.EasyStruct),LONGSET{},
SYS.ADR(MuchText),
SYS.ADR(oom),
SYS.ADR("Retry|Abort"));
BEGIN
IF I.int.libNode.version >= 37 THEN
IF I.EasyRequest(NIL,SYS.ADR(ES),NIL,NIL)=0 THEN
HALT(0)
END;
ELSE
Request(oom);
END;
END OutOfMemHandler;
(*-------------------------------------------------------------------------*)
PROCEDURE AllocLine(sz: INTEGER): TextLinePtr;
VAR
a: TextLinePtr;
newchunk: MemChunkPtr;
BEGIN
INC(sz,SIZE(TextLine)-MaxLen); IF ODD(sz) THEN INC(sz) END;
IF MemIndex+sz<=ChunkSize THEN (* does mem fit into current chunk ? *)
INC(MemIndex,sz); (* increment index in current chunk *)
ELSE
NEW(newchunk); (* allocate new chunk *)
newchunk.prev := CurChunk; (* link chunk into list *)
CurChunk := newchunk;
MemIndex := sz;
END;
RETURN SYS.ADR(CurChunk.data[MemIndex-sz]);
END AllocLine;
PROCEDURE DisposeLines();
VAR chunk: MemChunkPtr;
BEGIN
WHILE CurChunk#NIL DO
chunk := CurChunk.prev;
DISPOSE(CurChunk);
CurChunk := chunk;
END;
MemIndex := ChunkSize;
END DisposeLines;
(*-------------------------------------------------------------------------*)
(* $Debug- *)
PROCEDURE Busy;
(* $DataChip+ *)
TYPE Data = ARRAY 36 OF INTEGER;
CONST ClockData = Data(
00000U,00000U,
00400U,007C0U, 00000U,007C0U, 00100U,00380U, 00000U,007E0U,
007C0U,01FF8U, 01FF0U,03FECU, 03FF8U,07FDEU, 03FF8U,07FBEU,
07FFCU,0FF7FU, 07EFCU,0FFFFU, 07FFCU,0FFFFU, 03FF8U,07FFEU,
03FF8U,07FFEU, 01FF0U,03FFCU, 007C0U,01FF8U, 00000U,007E0U,
00000U,00000U);
BEGIN
IF Window#NIL THEN
I.OldModifyIDCMP(Window,MyIdcmp-LONGSET{I.rawKey,I.mouseButtons});
I.SetPointer(Window,ClockData,16,16,-6,0);
END;
END Busy;
PROCEDURE UnBusy;
BEGIN
IF Window#NIL THEN
I.ClearPointer(Window);
I.OldModifyIDCMP(Window,MyIdcmp);
END;
END UnBusy;
(*------ Scroll: ------*)
PROCEDURE MakeThink(sync,fast,always: BOOLEAN);
VAR m: INTEGER;
BEGIN
IF Scrollable THEN
m := 1;
IF ~always THEN
IF lace & ~fast THEN m := 2 END;
IF ~sync THEN INC(m,m*2) END;
END;
IF (m=1) OR (frame MOD m=0) THEN
CASE scrollmode OF
| 0: I.MakeScreen(Screen);
e.Forbid; g.MrgCop(I.ViewAddress()); e.Permit;
g.WaitTOF;
| 1: g.ScrollVPort(SYS.ADR(Screen.viewPort));
g.WaitTOF;
ELSE
I.MakeScreen(Screen);
I.RethinkDisplay();
END;
END;
INC(frame);
END;
END MakeThink;
(*------ Clear Display: ------*)
PROCEDURE ClearBitMaps;
VAR i: INTEGER;
BEGIN
g.SetRast(rp,0);
IF Scrollable THEN
ri.ryOffset := 0;
ScreenPos := 0;
MakeThink(f,f,w);
END;
END ClearBitMaps;
(*-------------------------------------------------------------------------*)
(*------ Read one TextLine into a Variable: ------*)
PROCEDURE GetTextLine(): TextLinePtr;
(* returns NIL at EOF *)
VAR
l: TextLinePtr;
sz,wd,i,j: INTEGER;
txt: ARRAY MaxLen+1 OF CHAR;
num: ARRAY 10 OF INTEGER;
newcol: BOOLEAN;
oldstyle: SHORTSET;
PROCEDURE GetCh();
BEGIN
IF RQPos=RQLen THEN
RQLen := d.Read(MyFile,Buffer,SIZE(Buffer));
IF RQLen<0 THEN Request(rwerr) END;
RQPos := 0;
END;
IF RQLen=0 THEN c := 0X ELSE
c := Buffer[RQPos]; IF c=0X THEN c:=1X END;
INC(RQPos); INC(le);
END;
END GetCh;
BEGIN
IF RQLen=0 THEN RETURN NIL END;
sz := 0; wd := 0; le := 0;
IF Italic IN style THEN IF Bold IN style THEN txt[sz] := boldit ELSE txt[sz] := italic END; INC(sz)
ELSE IF Bold IN style THEN txt[sz] := bold; INC(sz) END END;
IF Ulin IN style THEN txt[sz] := ulineon; INC(sz) END;
IF Inv IN style THEN txt[sz] := CHR(fg+4*bg+1); INC(sz)
ELSIF (fg#1) OR (bg#0) THEN txt[sz] := CHR(bg+4*fg+1); INC(sz) END;
LOOP
LOOP
GetCh;
IF SYS.VAL(CHAR,SYS.VAL(SHORTSET,c)*SHORTSET{0..6})#1BX THEN EXIT END;
i := -1;
REPEAT
GetCh;
IF (c>=30X) & (c<=39X) THEN
INC(i); num[i] := 0;
REPEAT
num[i] := 10*num[i]+ORD(c)-ORD(30X); GetCh;
UNTIL (c<30X) OR (c>39X);
END;
c := CAP(c);
UNTIL (c>=3FX(*"?"*)) & (c<=5AX) OR (c=0X) OR (i=9);
IF c=4DX THEN
newcol := f; oldstyle := style; j := 0;
IF i=-1 THEN i:=0; num[0] := 0 END;
WHILE (i>=j) & (sz<MaxLen-1) DO
CASE num[j] OF
0: style := SHORTSET{}; fg := 1; bg := 0; newcol := w |
1: INCL(style,Bold) |
2: fg := 2; IF onePlane THEN fg := 1 END; newcol := w (* I hope this is correct *) |
3: INCL(style,Italic) |
4: INCL(style,Ulin) |
7: INCL(style,Inv); newcol := w |
30..37: fg := (num[j]-30) MOD 4; IF onePlane & (fg>1) THEN fg:=1 END; newcol := w |
40..47: bg := (num[j]-40) MOD 4; IF onePlane & (bg>1) THEN bg:=1 END; newcol := w |
ELSE END;
INC(j);
END;
IF (oldstyle#style) & (sz<MaxLen) THEN
IF Italic IN style THEN IF Bold IN style THEN txt[sz] := boldit ELSE txt[sz] := italic END;
ELSE IF Bold IN style THEN txt[sz] := bold ELSE txt[sz] := plain END;
END;
INC(sz);
IF (Ulin IN style) THEN
IF ~((Ulin IN oldstyle)) & (sz<MaxLen) THEN
txt[sz] := ulineon;
INC(sz);
END;
ELSE
IF (Ulin IN oldstyle) & (sz<MaxLen) THEN
txt[sz] := ulineoff;
INC(sz);
END;
END;
END;
IF newcol & (sz<MaxLen) THEN
IF Inv IN style THEN txt[sz] := CHR(fg+4*bg+1)
ELSE txt[sz] := CHR(bg+4*fg+1) END;
INC(sz);
END;
END; (* IF c="m" THEN *)
END; (* LOOP *)
CASE c OF
20X.. 7FX: txt[sz] := c; INC(sz); INC(wd) |
0A1X..0FFX: txt[sz] := c; INC(sz); INC(wd) |
8X: (* BS *) IF wd>0 THEN DEC(sz); DEC(wd); END |
9X: (* TAB *)
REPEAT
txt[sz] := 20X; INC(sz); INC(wd)
UNTIL (sz=MaxLen) OR (wd=NumColumns) OR (sz MOD tabw=0) |
0A0X: txt[sz] := 20X; INC(sz); INC(wd) |
0AX,0X,0CX: EXIT |
ELSE END;
IF (wd>=NumColumns) OR (sz>=MaxLen) THEN EXIT END;
END;
txt[sz] := 0X; INC(sz);
l := AllocLine(sz);
l.len := le; l.size:= sz;
WHILE sz>0 DO DEC(sz); l.text[sz]:=txt[sz] END;
RETURN l;
END GetTextLine;
(*------ Write Line to Screen: ------*)
PROCEDURE Type(pos: INTEGER; line: TextLinePtr);
VAR
style: SHORTSET;
front,back: SHORTINT;
c: CHAR;
last,i,x: INTEGER;
strPtr: UNTRACED POINTER TO ARRAY 256 OF CHAR;
BEGIN
g.SetDrMd(rp,g.jam2);
IF Scrollable THEN
i := NuScreen.depth;
REPEAT
DEC(i);
g.BltClear(SYS.VAL(e.APTR,SYS.VAL(LONGINT,BM.planes[i])+pos*LineSize),LineSize,LONGSET{});
UNTIL i=0;
END;
i := 0; x := 0; style := SHORTSET{}; front := 1; back := 0;
LOOP
WHILE line.text[i]<" " DO
c := line.text[i];
IF c=0X THEN EXIT END;
CASE c OF
plain : style := style - SHORTSET{g.bold,g.italic} |
italic : EXCL(style,g.bold); INCL(style,g.italic) |
bold : INCL(style,g.bold); EXCL(style,g.italic) |
boldit : style := style + SHORTSET{g.bold,g.italic} |
ulineon : INCL(style,g.underlined) |
ulineoff: EXCL(style,g.underlined) |
1X..10X : DEC(c);
front := SHORT(ORD(c)) DIV 4;
back := SHORT(ORD(c)) MOD 4 |
ELSE END;
INC(i);
END;
strPtr := SYS.ADR(line.text[i]); last := i;
REPEAT INC(i) UNTIL line.text[i]<" ";
SYS.SETREG(0,g.SetSoftStyle(rp,style,-SHORTSET{}));
g.SetAPen(rp,front);
g.SetBPen(rp,back);
g.Move(rp,fontWidth*x,fontHeight*pos+fontBaseLine);
g.Text(rp,strPtr^,i-last);
INC(x,i-last);
END;
END Type;
PROCEDURE CopyScrollLine(pos: INTEGER);
(* Kopiert die an pos geschriebene Zeile auf den entsprechenden DoubleBuffer-Bereich *)
(*
* ACHTUNG: Darf nur aufgerufen werden, wenn Scrollable TRUE ist!
*)
VAR
y,z: INTEGER;
BEGIN
y := pos*fontHeight;
z := PageHeight;
IF pos>=NumLines THEN z := -z END;
SYS.SETREG(0,g.BltBitMap(BM, 0,y, BM, 0,y+z, NuScreen.width,fontHeight, 0C0X, SHORTSET{0..7}, NIL));
END CopyScrollLine;
(*------ Write String to Screen (as bottom line): ------*)
VAR writeText: TextLine;
PROCEDURE CopyToWriteText(String: StringPtr);
BEGIN
writeText := FirstLine^;
i := SHORT(str.Length(String^));
IF i>=NumColumns THEN i := NumColumns-1 END;
writeText.text[i+1] := 0X;
writeText.size := i;
REPEAT
writeText.text[i] := String[i];
DEC(i)
UNTIL i<0;
END CopyToWriteText;
(*------ Write String to Screen (at any position): ------*)
PROCEDURE TypeTo(VAR text: TextLine; pos: INTEGER);
BEGIN
IF pos<NumLines THEN
IF ~Scrollable THEN
Type(pos,SYS.ADR(text));
ELSE
INC(pos,ScreenPos);
Type(pos,SYS.ADR(text));
CopyScrollLine(pos);
END;
END;
END TypeTo;
(*------ Write String to Screen (at any position): ------*)
PROCEDURE WriteTo(String: StringPtr; pos: INTEGER);
BEGIN
CopyToWriteText(String);
TypeTo(writeText,pos);
END WriteTo;
(*------ Write Line at Bottom of Text: ------*)
PROCEDURE AddBottomLine(Line: TextLinePtr; Fast: BOOLEAN);
VAR
i,j: INTEGER;
y: INTEGER;
BEGIN
IF ~Scrollable THEN
g.SetAPen(rp,0); g.SetBPen(rp,0);
IF Fast THEN
g.ScrollRaster(rp,0,fontHeight,0,0,NuScreen.width-1,NuScreen.height-1);
IF Sync THEN g.WaitTOF END;
ELSE
i := fontHeight;
REPEAT
g.ScrollRaster(rp,0,1,0,0,NuScreen.width-1,NuScreen.height-1);
IF Sync THEN g.WaitTOF END;
DEC(i);
UNTIL i=0;
END;
Type(NumLines-1,Line);
ELSE
Type(ScreenPos+NumLines,Line);
y := ScreenPos*fontHeight;
IF Fast THEN
INC(ri.ryOffset,fontHeight);
MakeThink(Sync,w,f);
SYS.SETREG(0,g.BltBitMap(BM, 0,y+PageHeight, BM, 0,y, NuScreen.width,fontHeight, 0C0X, SHORTSET{0..7}, NIL));
ELSE
i := fontHeight;
REPEAT
INC(ri.ryOffset);
MakeThink(Sync,f,f);
SYS.SETREG(0,g.BltBitMap(BM, 0,y+PageHeight, BM, 0,y, NuScreen.width,1, 0C0X, SHORTSET{0..7}, NIL));
INC(y);
DEC(i);
UNTIL i=0;
END;
INC(ScreenPos);
IF ScreenPos=NumLines THEN
ScreenPos := 0;
ri.ryOffset := 0;
END;
END;
END AddBottomLine;
(*------ Check whether BottomLine.next is NIL or not: ------*)
PROCEDURE TryBottomnext(): BOOLEAN;
(* returns TRUE if BottomLine.next#NIL END; *)
BEGIN
IF (BottomLine.next=NIL) & (MyFile#NIL) THEN
SignalNewData := w;
SYS.SETREG(0,e.Wait(mySig));
SignalNewData := f;
END;
RETURN BottomLine.next#NIL;
END TryBottomnext;
(*------ Scroll down one Line: ------*)
PROCEDURE ScrollDown(Fast: BOOLEAN);
BEGIN
IF TryBottomnext() THEN
BottomLine := BottomLine.next;
INC(AnzLines);
INC(TextLength,BottomLine.len);
ELSE RETURN END;
IF AnzLines>=NumLines THEN TopLine := TopLine.next END;
AddBottomLine(BottomLine,Fast);
END ScrollDown;
(*------ Scroll Up one Line: ------*)
PROCEDURE ScrollUp(Fast: BOOLEAN);
VAR
i,j: INTEGER;
y: INTEGER;
BEGIN
IF (TopLine.prev#NIL) & (TopLine.prev.prev#NIL) THEN
TopLine := TopLine.prev;
DEC(TextLength,BottomLine.len);
DEC(AnzLines);
BottomLine := BottomLine.prev;
IF ~Scrollable THEN
g.SetAPen(rp,0); g.SetBPen(rp,0);
IF Fast THEN
g.ScrollRaster(rp,0,-fontHeight,0,0,NuScreen.width-1,NuScreen.height-1);
IF Sync THEN g.WaitTOF END;
ELSE
i := fontHeight;
REPEAT
g.ScrollRaster(rp,0,-1,0,0,NuScreen.width-1,NuScreen.height-1);
IF Sync THEN g.WaitTOF END;
DEC(i)
UNTIL i=0;
END;
Type(0,TopLine.prev);
ELSE
IF ScreenPos=0 THEN
ri.ryOffset := NumLines*fontHeight;
ScreenPos := NumLines-1;
ELSE
DEC(ScreenPos);
END;
Type(ScreenPos,TopLine.prev);
y := ScreenPos*fontHeight;
IF Fast THEN
DEC(ri.ryOffset,fontHeight);
MakeThink(Sync,w,f);
SYS.SETREG(0,g.BltBitMap(BM, 0,y, BM, 0,y+PageHeight, NuScreen.width,fontHeight, 0C0X, SHORTSET{0..7}, NIL));
ELSE
INC(y,fontHeight);
i := fontHeight;
REPEAT
DEC(ri.ryOffset);
MakeThink(Sync,f,f);
DEC(y);
SYS.SETREG(0,g.BltBitMap(BM, 0,y, BM, 0,y+PageHeight, NuScreen.width,1, 0C0X, SHORTSET{0..7}, NIL));
DEC(i);
UNTIL i=0;
END;
END;
END; (* IF TopLine#NIL ... *)
END ScrollUp;
(*------ Undo last AddBottomLine: ------*)
PROCEDURE DelLine();
VAR
i,j: INTEGER;
y: INTEGER;
text: TextLine;
BEGIN
IF ~Scrollable THEN
g.SetAPen(rp,0); g.SetBPen(rp,0);
IF Fast THEN
g.ScrollRaster(rp,0,-fontHeight,0,0,NuScreen.width-1,NuScreen.height-1);
IF Sync THEN g.WaitTOF END;
ELSE
i := fontHeight;
REPEAT
g.ScrollRaster(rp,0,-1,0,0,NuScreen.width-1,NuScreen.height-1);
IF Sync THEN g.WaitTOF END;
DEC(i)
UNTIL i=0;
END;
IF TopLine.prev#NIL THEN Type(0,TopLine.prev) ELSE Type(0,FirstLine) END;
ELSE
IF ScreenPos=0 THEN
ri.ryOffset := NumLines*fontHeight;
ScreenPos := NumLines;
END;
DEC(ScreenPos);
IF TopLine.prev#NIL THEN Type(ScreenPos,TopLine.prev) ELSE Type(ScreenPos,FirstLine) END;
y := (ScreenPos+1)*fontHeight;
IF Fast THEN
DEC(ri.ryOffset,fontHeight);
MakeThink(Sync,w,f);
DEC(y,fontHeight);
SYS.SETREG(0,g.BltBitMap(BM, 0,y, BM, 0,y+PageHeight, NuScreen.width,fontHeight , 0C0X, SHORTSET{0..7}, NIL));
ELSE
i := fontHeight;
REPEAT
DEC(ri.ryOffset);
MakeThink(Sync,f,f);
DEC(y);
SYS.SETREG(0,g.BltBitMap(BM, 0,y, BM, 0,y+PageHeight, NuScreen.width,1, 0C0X, SHORTSET{0..7}, NIL));
DEC(i);
UNTIL i=0;
END;
END;
END DelLine;
(*------ Convert Integer to String: ------*)
PROCEDURE IntToStr(VAR String: String;
At,Chars: INTEGER;
int: LONGINT);
VAR
Cnt: INTEGER;
Ziff: LONGINT;
BEGIN
INC(Chars,At);
IF (str.Length(String)<Chars) & (Chars < SIZE(String)) THEN
String[Chars] := 0X
END;
REPEAT
DEC(Chars);
String[Chars] := CHR(int MOD 10 + ORD(30X)); int := int DIV 10;
UNTIL (Chars=At) OR (int=0);
WHILE Chars>At DO DEC(Chars); String[Chars] := 20X END;
END IntToStr;
(*------ Convert String to Integer: ------*)
PROCEDURE StrToInt(str: StringPtr; base: INTEGER): LONGINT;
VAR
i,j: INTEGER;
num: LONGINT;
ch : CHAR;
neg: BOOLEAN;
BEGIN
num := 0; i := 0; neg := f;
IF str^[0] = '-' THEN str:=SYS.ADR(str[1]); neg := w END;
IF str^[0] = '$' THEN str:=SYS.ADR(str[1]); base:=16 END;
IF (str^[0]='0')&(CAP(str^[1])='X') THEN str:=SYS.ADR(str[2]); base:=16 END;
LOOP
IF i=LEN(str^) THEN EXIT END;
ch := CAP(str^[i]);
IF ch=0X THEN EXIT END;
j := ORD(ch);
CASE ch OF
"0".."9": DEC(j,ORD('0')) |
"A".."F": DEC(j,ORD('A')-10);
IF base=10 THEN base:=16; i:=-1; j:=0; num:=0 END;
ELSE EXIT
END;
num := num * base + j;
INC(i);
END;
IF neg THEN num := -num END;
RETURN num
END StrToInt;
(*-------------------------------------------------------------------------*)
PROCEDURE GetStr(name: StringPtr; VAR str: String);
VAR i: INTEGER;
BEGIN
i := -1;
REPEAT
INC(i); str[i] := name^[i]
UNTIL (name^[i]=0X) OR (i=LEN(str)-1);
str[i] := 0X
END GetStr;
(*-------------------------------------------------------------------------*)
PROCEDURE GetLength(t: TextLinePtr);
BEGIN
TextLength := 0; AnzLines := 0;
WHILE t#NIL DO INC(AnzLines); INC(TextLength,t.len); t := t.prev END;
END GetLength;
(*-------------------------------------------------------------------------*)
PROCEDURE NewDisplay();
(* Zeichnet ab BottomLine neu *)
VAR
i: INTEGER;
l: TextLinePtr;
BEGIN
ClearBitMaps;
l := BottomLine.prev;
IF l#NIL THEN BottomLine := l END;
l := BottomLine;
i := NumLines-1;
WHILE (i>0) & TryBottomnext() DO
BottomLine := BottomLine.next;
DEC(i);
END;
WHILE (i>0) & (l.prev#NIL) DO
l := l.prev;
DEC(i);
END;
TopLine := l.next;
WHILE i<NumLines DO
BottomLine := l;
TypeTo(BottomLine^,i);
INC(i);
l := l.next;
END;
GetLength(BottomLine);
Scroll := f;
END NewDisplay;
(*-------------------------------------------------------------------------*)
PROCEDURE * ShowProc;
VAR
l: TextLinePtr;
Down: BOOLEAN; (* Scroll-Direction *)
End: BOOLEAN; (* Quit next time Space is pressed ? *)
i,j,k,m: INTEGER;
MyMsg: I.IntuiMessage; (* contains Message *)
Shift: BOOLEAN; (* Shifted Keystroke ? *)
Alt: BOOLEAN; (* Altered Keystroke ? *)
Find,FindStr: ARRAY 80 OF CHAR; (* findstring / capitalized findstring *)
Goto: ARRAY 10 OF CHAR; (* string containing goto line # *)
li: LONGINT; (* longint value of line to go to *)
flen: INTEGER; (* length of findstring *)
HiText: TextLine; (* Highlited textline *)
OldHiText: TextLinePtr; (* original, un-hilited text *)
found: BOOLEAN; (* TRUE, if find was successful *)
chr: CHAR; (* converted keycode *)
PROCEDURE WaitAllRead();
BEGIN
IF MyFile#NIL THEN
Busy;
SignalAllRead := w;
SYS.SETREG(0,e.Wait(mySig));
SignalAllRead := f;
UnBusy;
END;
END WaitAllRead;
PROCEDURE HiLite(at,len: INTEGER);
(* Hilites len chars of BottomLine.text starting at position at *)
VAR
c: INTEGER;
col: CHAR;
BEGIN
OldHiText := BottomLine; HiText := OldHiText^; BottomLine := SYS.ADR(HiText);
IF at+len+2<MaxLen THEN
c := 0; col := 5X;
WHILE c<at DO
IF HiText.text[c]<CHR(17) THEN col := HiText.text[c] END;
INC(c);
END;
HiText.text[at] := CHR(17-ORD(col));
c := at; INC(len,at);
WHILE c<len DO
HiText.text[c+1] := OldHiText.text[c];
INC(c);
END;
HiText.text[c+1] := col;
REPEAT
HiText.text[c+2] := OldHiText.text[c];
INC(c);
UNTIL HiText.text[c-1]=0X;
END;
IF HiText.next#NIL THEN HiText.next.prev := SYS.ADR(HiText) END;
IF HiText.prev#NIL THEN HiText.prev.next := SYS.ADR(HiText) END;
END HiLite;
PROCEDURE UnHiLite();
BEGIN
IF HiText.next#NIL THEN HiText.next.prev := OldHiText END;
IF HiText.prev#NIL THEN HiText.prev.next := OldHiText END;
END UnHiLite;
PROCEDURE ChkBotNewDisp;
VAR
c: INTEGER;
t: LONGINT;
BEGIN
IF ~ found THEN
I.DisplayBeep(NIL);
IF TopLine.prev=NIL THEN BottomLine := TopLine
ELSE BottomLine := TopLine.prev END;
END;
NewDisplay;
IF found THEN UnHiLite END;
END ChkBotNewDisp;
PROCEDURE Search(): BOOLEAN;
(* searches string and hilites it if found. result is TRUE if string found *)
BEGIN
i := 0;
IF BottomLine.len<NumColumns THEN m := BottomLine.len ELSE m := NumColumns END;
WHILE i<BottomLine.size DO
j := 0; k := i;
WHILE CAP(BottomLine.text[k])=FindStr[j] DO
INC(j); INC(k);
IF FindStr[j]=0X THEN
SYS.SETREG(0,TryBottomnext());
FindLine := BottomLine;
HiLite(k-flen,flen);
found := w; RETURN w;
END;
END;
INC(i);
END;
RETURN f;
END Search;
PROCEDURE DisplayInfo(Fast: BOOLEAN);
VAR IStr: String;
BEGIN
(* File: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx xx % (xxxxxx of xxxxxx Bytes) xxxxxx Lines *)
IStr := "XFile: "; IStr[0] := 7X;
IF onePlane THEN IStr[0] := 2X END;
Append(IStr,SYS.ADR(OldName));
Append(IStr,SYS.ADR(" "));
IStr[36] := 0X;
Append(IStr,SYS.ADR("xxx % (xxxxxx of xxxxxx Bytes) xxxxxx Lines"));
IntToStr(IStr,36,3,TextLength * 100 DIV FileLength);
IntToStr(IStr,43,6,TextLength);
IntToStr(IStr,53,6,FileLength);
IntToStr(IStr,67,6,AnzLines-1);
i := 79;
REPEAT IStr[i] := 20X; INC(i) UNTIL (i>=255) OR (i>=NumColumns+2);
IStr[i] := 0X;
CopyToWriteText(SYS.ADR(IStr));
AddBottomLine(SYS.ADR(writeText),Fast);
Info := w;
END DisplayInfo;
PROCEDURE GetString(VAR str: ARRAY OF CHAR; int: BOOLEAN);
VAR
msg: I.IntuiMessagePtr;
class: LONGSET;
oldheight: INTEGER;
BEGIN
MakeThink(f,f,w);
Busy;
NuWindow.leftEdge := 100;
NuWindow.topEdge := NuScreen.height DIV 2 - 6;
IF Scrollable THEN INC(NuWindow.topEdge,ri.ryOffset) END;
NuWindow.width := NuScreen.width-200;
NuWindow.height := Screen.font.ySize+4;
NuWindow.blockPen := 1;
NuWindow.idcmpFlags := LONGSET{I.gadgetUp,I.activeWindow,I.inactiveWindow};
NuWindow.flags := LONGSET{I.rmbTrap,I.activate};
NuWindow.firstGadget := SYS.ADR(StrGadget);
NuWindow.screen := Screen;
NuWindow.type := I.customScreen;
StrGadget.leftEdge := 4;
StrGadget.topEdge := 2;
StrGadget.width := NuWindow.width-8;
StrGadget.height := NuWindow.height-4;
StrGadget.activation := {I.stringCenter,I.relVerify};
IF int THEN INCL(StrGadget.activation,I.longint) END;
StrGadget.gadgetType := I.strGadget;
StrGadget.specialInfo:= SYS.ADR(StrInfo);
StrInfo.buffer := SYS.ADR(str);
StrInfo.maxChars := SHORT(LEN(str))-1;
oldheight := Screen.height;
IF Scrollable THEN INC(Screen.height,Screen.height) END;
win := I.OpenWindow(NuWindow);
Screen.height := oldheight;
IF win#NIL THEN
e.WaitPort(win.userPort);
SYS.SETREG(0,I.ActivateGadget(StrGadget,win,NIL));
LOOP
e.WaitPort(win.userPort);
msg := e.GetMsg(win.userPort);
IF msg#NIL THEN
class := msg.class;
e.ReplyMsg(msg);
IF I.gadgetUp IN class THEN
EXIT
ELSIF I.inactiveWindow IN class THEN
I.OldActivateWindow(win);
g.WaitTOF; g.WaitTOF; g.WaitTOF;
SYS.SETREG(0,I.ActivateGadget(StrGadget,win,NIL));
END;
END;
END;
I.CloseWindow(win); win := NIL;
END;
UnBusy;
END GetString;
PROCEDURE Help; (* executed when HELP or H is pressed *)
TYPE
UsageType = ARRAY 26 OF StringPtr;
CONST
Usage = UsageType(SYS.ADR(""),
SYS.ADR("\x13 \x15 MuchMore V3.2.7 Commands: "),
SYS.ADR(""),
SYS.ADR(" \x0dSpace\x05,\x0d LMB\x05: Start / Stop scrolling. Quit at end of file."),
SYS.ADR(" \x0dBackSpace\x05,\x0d RMB\x05: Start / Stop scrolling backwards."),
SYS.ADR(" \x0dUp\x05/\x0dDown\x05: Move one line \x0dup\x05 or \x0ddown\x05."),
SYS.ADR(" \x0dShift \x05+\x0d Up\x05/\x0dDn\x05: Start / Stop quick scrolling \x0dup\x05 or \x0ddown\x05."),
SYS.ADR(" \x0dControl\x05: Increase scroll speed"),
SYS.ADR(" \x0dAlt\x05+\x0dUp\x05/\x0dDn\x05,\x0d PgUp\x05/\x0dDn\x05: Move one page \x0dup\x05 or \x0ddown\x05."),
SYS.ADR(" \x0dT\x05,\x0d Home \x05/\x0d B\x05,\x0d End\x05: Goto \x0dt\x05op / \x0db\x05ottom of text."),
SYS.ADR(" \x0dF\x05,\x0dN\x05,\x0dP\x05: \x0dF\x05ind string, \x0dN\x05ext, \x0dP\x05revious occurance"),
SYS.ADR(" \x0dShift \x05+\x0d Fn\x05: Set textmarker #n to current position"),
SYS.ADR(" \x0dFn\x05: Goto marker #n or set marker #n if it wasn't set yet"),
SYS.ADR(" \x0dG\x05: \x0dG\x05oto line #n"),
SYS.ADR(" \x0dNK 0\x05: Display Filelength etc."),
SYS.ADR(" \x0dShift \x05+\x0d Alt \x05+\x0d O\x05: Create print\x0do\x05ut of the text"),
SYS.ADR(" \x0dW\x05: \x0dW\x05rite block between Marker #1 and #2 to file or prt"),
SYS.ADR(" \x0dL\x05: \x0dL\x05oad new text"),
SYS.ADR(" \x0dHELP\x05,\x0d H\x05: Show Commands."),
SYS.ADR(" \x0dESC\x05,\x0d Q\x05,\x0d X\x05,\x0d NK 5\x05:\x0d Q\x05uit."),
SYS.ADR(""),
SYS.ADR("© \x131992 Fridtjof Siebert, Nobileweg 67, D-7000 Stuttgart 40"),
SYS.ADR(" \x131993 Christian Stiens, Heustiege 2, D-4710 Lüdinghausen"),
SYS.ADR(" \x13Please refer to MuchMore.ReadMe for a detailed copyright notice"),
SYS.ADR(""),
SYS.ADR(" This is another product of the Amiga MODULA & OBERON Klub Stuttgart - \x0d\x13AMOK"));
VAR
i,j: INTEGER;
BEGIN
ClearBitMaps();
j := (NumLines - 26) DIV 2; IF j<0 THEN j:=0 END;
i := 0;
WHILE (i<26) & (i+j<NumLines) DO
WriteTo(Usage[i],j+i);
INC(i);
END;
LOOP
e.WaitPort(Window.userPort);
MyMsgPtr := e.GetMsg(Window.userPort);
IF (LONGSET{I.rawKey,I.mouseButtons}*MyMsgPtr.class#LONGSET{}) & (MyMsgPtr.code<128) THEN EXIT END;
e.ReplyMsg(MyMsgPtr);
END;
e.ReplyMsg(MyMsgPtr);
BottomLine := TopLine;
NewDisplay
END Help;
PROCEDURE Bottom; (* executed when END or B is pressed *)
BEGIN
WaitAllRead;
BottomLine := LastLine;
NewDisplay
END Bottom;
PROCEDURE Space(): BOOLEAN; (* executed if space or LMB is pressed *)
(* IF result=w THEN EXIT END *)
VAR oldFast: BOOLEAN;
BEGIN
oldFast := Fast;
Fast := Shift;
IF (MyFile=NIL) & (BottomLine.next=NIL) THEN
IF End THEN RETURN w ELSE End:=w END;
ELSE
End := f;
END;
IF Down THEN
IF Scroll OR End THEN DisplayInfo(oldFast) END;
Scroll := ~Scroll;
ELSE
Down := w;
Scroll := w;
END;
RETURN f;
END Space;
PROCEDURE BackSpace; (* executed if backspace or RMB is pressed *)
BEGIN
Fast := Shift;
Scroll := Down OR ~ Scroll;
Down := f
END BackSpace;
BEGIN
(* $IF SmallData *)
SYS.SETREG(13,e.exec.thisTask.userData);
(* $END *)
SYS.SETREG(0,e.Wait(mySig));
Down := w; End := f; Find[0] := 0X; Goto[0] := 0X;
LOOP
IF NewDisp THEN NewDisp := f; NewDisplay END;
(*------ Type Text: ------*)
LOOP
IF Scroll THEN
IF Down THEN
ScrollDown(Fast);
Scroll := (MyFile#NIL) OR (BottomLine.next#NIL);
ELSE
ScrollUp(Fast);
Scroll := (TopLine.prev#NIL) & (TopLine.prev.prev#NIL);
END;
ELSE
MakeThink(f,f,w);
e.WaitPort(Window.userPort);
END;
MyMsgPtr := e.GetMsg(Window.userPort);
IF (MyMsgPtr#NIL) THEN
IF ~(I.inactiveWindow IN MyMsgPtr.class) THEN EXIT END;
e.ReplyMsg(MyMsgPtr);
I.OldModifyIDCMP(Window,MyIdcmp-LONGSET{I.mouseButtons});
e.WaitPort(Window.userPort);
I.OldModifyIDCMP(Window,MyIdcmp);
END;
END;
MyMsg := MyMsgPtr^;
e.ReplyMsg(MyMsgPtr);
IF (I.rawKey IN MyMsg.class) & (MyMsg.code<80H) OR
(I.mouseButtons IN MyMsg.class) & ({ie.leftButton,ie.rightButton}*MyMsg.qualifier#{})
THEN
IF ~Info THEN
IF MyMsg.code=0FH THEN DisplayInfo(Fast); Scroll := f END;
ELSE
DelLine;
Info := f
END;
END;
Shift := {} # {ie.lShift,ie.rShift,ie.capsLock} * MyMsg.qualifier;
Alt := {} # {ie.lAlt ,ie.rAlt} * MyMsg.qualifier;
Sync := ~ ( ie.control IN MyMsg.qualifier);
IF ~(Sync OR Alt) THEN Shift := w END;
IF I.mouseButtons IN MyMsg.class THEN
IF (ie.leftButton IN MyMsg.qualifier) & Space() THEN EXIT
ELSIF ie.rightButton IN MyMsg.qualifier THEN BackSpace END;
ELSIF (I.rawKey IN MyMsg.class) & (MyMsg.code<80H) THEN
CASE MyMsg.code OF
| 40H: IF Space() THEN EXIT END (* Space *)
| 41H: BackSpace (* BackSpace *)
| 4DH,1EH,1FH: (* Down *)
IF Shift THEN
Scroll := ~(Down & Scroll) OR ~ Fast;
Fast := w; Down := w;
ELSE
IF Alt OR (MyMsg.code=1FH) THEN
IF BottomLine.next#NIL THEN BottomLine := BottomLine.next END;
NewDisplay;
ELSE
ScrollDown(~ Shift);
END;
Scroll := f;
END
| 4CH,3EH,3FH: (* Up *)
IF Shift THEN
Scroll := Down OR ~ Scroll OR ~ Fast;
Fast := w; Down := f;
ELSE
IF Alt OR (MyMsg.code=3FH) THEN
IF TopLine.prev#NIL THEN
i := NumLines-1;
BottomLine := TopLine;
WHILE (i>0) & (BottomLine.prev#NIL) DO
BottomLine := BottomLine.prev;
DEC(i);
END;
NewDisplay;
END;
ELSE
ScrollUp(~ Shift);
END;
Scroll := f;
END;
| 44H,43H: (* CR *)
ScrollDown(f);
Scroll := f;
| 3DH: BottomLine := FirstLine; NewDisplay (* Home *)
| 1DH: Bottom (* End *)
| 50H..59H: (* F1..F10 *)
i := MyMsg.code-50H;
IF ~ Shift & (TextMarkers[i]#NIL) THEN
BottomLine := TextMarkers[i];
IF BottomLine.prev#NIL THEN BottomLine := BottomLine.prev END;
NewDisplay;
ELSE
TextMarkers[i] := TopLine;
END
| 5FH: Help
| 45H,2EH: IF ~ Alt THEN EXIT END (* Quit *)
ELSE
IF MyMsg.code<40H THEN (* examine vanilla keycode: *)
chr := KeyMap[MyMsg.code];
CASE chr OF
| "t": BottomLine := FirstLine; NewDisplay (* Home *)
| "b": Bottom; (* End *)
| "f","n","p": (* Find, Next, Previous *)
IF chr="f" THEN
GetString(Find,f); FindLine := NIL; flen := 0;
LOOP
FindStr[flen] := CAP(Find[flen]);
IF FindStr[flen]>80X THEN DEC(FindStr[flen],32)
ELSIF FindStr[flen]=0X THEN EXIT END;
INC(flen);
END;
ClearBitMaps();
END;
found := f;
IF FindStr[0]#0X THEN
Busy;
i := NumLines;
IF FindLine#NIL THEN FindLine := FindLine.next END;
WHILE (i>0) & (BottomLine#NIL) & (BottomLine#FindLine) DO
BottomLine := BottomLine^.prev; DEC(i);
END;
IF (BottomLine#FindLine) OR (BottomLine=NIL) THEN BottomLine := TopLine END;
IF chr#"p" THEN (* next *)
WHILE (BottomLine#NIL) & ~ Search() DO
SYS.SETREG(0,TryBottomnext());
BottomLine := BottomLine.next;
END;
ELSE (* previous *)
IF BottomLine.prev#NIL THEN BottomLine:=BottomLine.prev END;
REPEAT
BottomLine := BottomLine.prev
UNTIL (BottomLine=NIL) OR Search();
END;
IF BottomLine#NIL THEN
li := NumLines DIV 2;
WHILE (li>0) & (BottomLine.prev#NIL) DO BottomLine := BottomLine.prev; DEC(li) END;
END;
UnBusy;
ELSE
BottomLine := NIL
END;
ChkBotNewDisp;
| "w": (* write block *)
IF (TextMarkers[0]#NIL) & (TextMarkers[1]#NIL) & ~ print & ~ save THEN
savefrom := 0; savesize := 0;
l := TextMarkers[0].prev; WHILE l.prev#NIL DO l := l.prev; INC(savefrom,l.len) END;
l := TextMarkers[1].prev; WHILE l#NIL DO INC(savesize,l.len); l := l.prev END;
l := TextMarkers[1]; i := NumLines; WHILE (i>1) & (l#NIL) DO DEC(i); INC(savesize,LONG(l.len)); l := l.next END;
DEC(savesize,savefrom);
IF savesize>0 THEN
GetString(WriteName,f);
WaitAllRead; save := w; e.Signal(SYS.ADR(Me.task),mySig); NewDisplay;
END
END
| "o": IF Shift & Alt & ~print & ~save THEN (* Printout *)
PStr := 'TYPE "'; Append(PStr,SYS.ADR(Name)); Append(PStr,SYS.ADR('" TO PRT:'));
WaitAllRead; print := w; e.Signal(SYS.ADR(Me.task),mySig);
END
| "l": ClearBitMaps; (* Load Text *)
NewText := w; e.Signal(SYS.ADR(Me.task),mySig);
REPEAT UNTIL (mySigBit IN e.Wait(mySig)) & ~ NewText |
| "g": (* goto *)
GetString(Goto,w);
li := SHORT(StrInfo.longInt);
Busy;
BottomLine := FirstLine;
WHILE (li>0) & TryBottomnext() DO
BottomLine := BottomLine.next;
DEC(li)
END;
UnBusy;
NewDisplay
| "h": Help (* Help *)
| "q","x": EXIT (* Quit *)
ELSE END;
END; (* IF MyMsg.code<40H THEN *)
END; (* CASE MyMsg.code OF *)
END; (* IF I.rawKey IN MyMsg.class THEN *)
END; (* LOOP *)
Done := w;
e.Signal(SYS.ADR(Me.task),mySig);
LOOP SYS.SETREG(0,e.Wait(LONGSET{})) END;
END ShowProc;
(* $Debug= *)
(*-------------------------- File Requester: ----------------------------*)
PROCEDURE FileReq(VAR Name: String);
CONST
dummy = u.user + 80000H;
taghail = dummy + 1;
window = dummy + 2;
leftEdge = dummy + 3; (* Initialize LeftEdge *)
topEdge = dummy + 4; (* Initialize TopEdge *)
width = dummy + 5;
height = dummy + 6;
hookFunc = dummy + 7; (* Hook function pointer *)
file = dummy + 8; (* Initial name of file follows *)
dir = dummy + 9; (* Initial string for filerequest dir *)
pattern = dummy + 10;
funcFlags = dummy + 20;
fiDir = u.user + 50;
longPath = 0;
patGad = 0;
VAR
fr: FileRequesterPtr;
pscr: I.ScreenPtr;
res: BOOLEAN;
PROCEDURE AllocAslRequest {asl,-48} (type{0}: LONGINT;
tag{8}..: e.APTR): FileRequesterPtr;
PROCEDURE FreeAslRequest {asl,-54} (fr{8}: FileRequesterPtr);
PROCEDURE RequestFile {asl,-42} (fr{8}: FileRequesterPtr): e.APTR;
PROCEDURE FileRequest{arp,-294}(VAR filereq{8}: FileRequester): BOOLEAN;
BEGIN
LOOP
j := SHORT(str.Length(Name));
WHILE (j>0) & (Name[j]#":") & (Name[j]#"/") DO DEC(j) END;
IF j=0 THEN j := -1 END;
i := 0;
WHILE i<=j DO Dirname[i] := Name[i]; INC(i) END; Dirname[i] := 0X;
j := 0;
REPEAT Filename[j] := Name[i]; INC(j); INC(i) UNTIL Name[i-1]=0X;
LOOP
IF I.int.libNode.version >= 37 THEN
pscr := I.LockPubScreen(NIL);
IF pscr#NIL THEN
I.ScreenToFront(pscr);
I.UnlockPubScreen(NIL,pscr);
EXIT
END;
END;
SYS.SETREG(0,I.WBenchToFront());
EXIT
END;
IF asl=NIL THEN asl := e.OpenLibrary("asl.library",36) END;
IF asl#NIL THEN
fr := AllocAslRequest(0,taghail, SYS.ADR(MuchText),
leftEdge,25,
topEdge, 15,
width, 300,
height, 184,
file, SYS.ADR(Filename),
dir, SYS.ADR(Dirname),
pattern, SYS.ADR(Pattern),
funcFlags,ASH(1,patGad),
u.done);
IF fr=NIL THEN Request(oom) END;
res := RequestFile(fr)#NIL;
IF res THEN
Filename := fr.ddef^;
Dirname := fr.ddir^;
END;
FreeAslRequest(fr);
IF ~res THEN EXIT END;
ELSE
IF arp=NIL THEN arp := e.OpenLibrary("arp.library",39) END;
IF arp#NIL THEN
FR.hail := SYS.ADR(MuchText);
FR.ddef := SYS.ADR(Filename);
FR.ddir := SYS.ADR(Dirname);
FR.flags2 := SHORTSET{longPath};
FR.wind := NIL;
IF ~FileRequest(FR) THEN EXIT END;
ELSE
Request(noarp)
END;
END;
Name := Dirname;
i := SHORT(str.Length(Name));
IF (i>0) THEN
CASE Name[i-1] OF "/",":": ELSE
Name[i] := "/"; INC(i);
END;
END;
j := 0;
LOOP
Name[i] := Filename[j];
IF (Name[i]=0X) OR (i=255) THEN EXIT END;
INC(i);
INC(j);
END;
Name[i] := 0X;
IF Screen#NIL THEN I.ScreenToFront(Screen) END;
IF Window#NIL THEN IF I.ActivateWindow(Window) THEN END END;
RETURN
END;
HALT(0);
END FileReq;
(*-------------------------- Decrunch: ----------------------------*)
PROCEDURE DirExists(name: ARRAY OF CHAR): BOOLEAN; (* $CopyArrays- *)
VAR lock: d.FileLockPtr;
result: BOOLEAN;
oldwp: e.APTR;
BEGIN
result := f;
oldwp := Me.windowPtr;
Me.windowPtr := -1;
lock := d.Lock(name,d.sharedLock);
IF lock # NIL THEN
result := w;
d.UnLock(lock)
END;
Me.windowPtr := oldwp;
RETURN result
END DirExists;
PROCEDURE RFProc; (* $EntryExitCode- *)
BEGIN
SYS.INLINE(016C0U, 04E75U)
END RFProc;
PROCEDURE Decrunch;
CONST
tagBase = u.user + ORD("X")*256 + ORD("P");
inName = tagBase+01H;
inFH = tagBase+02H;
outName = tagBase+10H;
password = tagBase+24H;
getError = tagBase+25H;
shortError = tagBase+31H;
typePacked = 1;
TYPE
XpkFib = STRUCT
type : LONGINT; (* Unpacked, packed, archive? *)
uLen : LONGINT;
cLen : LONGINT;
nLen : LONGINT;
uCur : LONGINT;
cCur : LONGINT;
id : LONGINT;
packer : ARRAY 6 OF CHAR;
subVersion : INTEGER;
masVersion : INTEGER;
flags : LONGSET;
head : ARRAY 16 OF CHAR;
ratio : LONGINT;
reserved : ARRAY 8 OF LONGINT;
END;
VAR
file: d.FileHandlePtr;
err: LONGINT;
xpkFib: XpkFib;
errBuf: ARRAY 81 OF CHAR;
PROCEDURE ExamineTags {xpk,-36}(VAR fib{8} : XpkFib;
tag1{9}.. : e.APTR): LONGINT;
PROCEDURE UnpackTags {xpk,-48}(tag1{8}.. : e.APTR): LONGINT;
BEGIN
Decrunched := f;
OldName := Name;
IF DirExists("T:") THEN Name := "T:" ELSE Name := "RAM:" END;
e.RawDoFmt("MM_decr.%lx",SYS.ADR(Me),RFProc,SYS.ADR(Name[str.Length(Name)]));
IF xpk=NIL THEN
xpk := e.OpenLibrary("xpkmaster.library",1);
END;
IF xpk#NIL THEN
err := ExamineTags(xpkFib,inFH,SYS.VAL(LONGINT,MyFile),u.done);
IF (err#0) & (err#-20) THEN
Request(oom)
END;
IF (err=-20) OR (xpkFib.type#typePacked) THEN
Name := OldName;
RETURN
END;
Busy;
err := UnpackTags(inFH, SYS.VAL(LONGINT,MyFile),
outName, SYS.ADR(Name),
password, SYS.ADR(Password),
getError, SYS.ADR(errBuf),
shortError, e.true,
u.done);
UnBusy;
IF err#0 THEN Request(errBuf) END;
file := d.Open(Name,d.oldFile);
IF file#NIL THEN
Decrunched := w;
d.OldClose(MyFile);
MyFile := file;
RETURN
ELSE
Request(cof);
END;
END;
Name := OldName;
END Decrunch;
(*----------------- Screen Mode Requester: ------------------------*)
PROCEDURE GetNode (VAR list: e.List; index: LONGINT): e.NodePtr;
VAR n: e.NodePtr;
BEGIN
n := list.head;
WHILE index > 0 DO
IF n.succ=NIL THEN RETURN NIL END;
n := n.succ;
DEC(index);
END;
RETURN n;
END GetNode;
PROCEDURE ScreenModeReq (VAR displayID : LONGINT): INTEGER;
CONST
gadLISTVIEW = 1;
gadBUTTONSave = 2;
gadBUTTONUse = 3;
gadBUTTONCancel= 4;
Topaz80 = g.TextAttr(SYS.ADR("topaz.font"), 8, SHORTSET{}, SHORTSET{});
TYPE
MyNodePtr = UNTRACED POINTER TO MyNode;
MyNode = STRUCT (node: e.Node)
displayID: LONGINT;
END;
VAR
ng : gt.NewGadget;
gad,glist : I.GadgetPtr;
win : I.WindowPtr;
pub : I.ScreenPtr;
result,index: INTEGER;
firstindex : INTEGER;
topborder : INTEGER;
terminated : BOOLEAN;
lvlist : e.List;
lvSelectedTag:LONGINT;
vi : e.APTR;
imsg : I.IntuiMessagePtr;
node : MyNodePtr;
dispID : LONGINT;
displayInfo : g.DisplayInfo;
nameInfo : g.NameInfo;
BEGIN
(* $IFNOT ClearVars *)
win := NIL; vi := NIL; glist := NIL; pub := NIL; result := 0;
(* $END *)
LOOP
pub := I.LockPubScreen(NIL); IF pub=NIL THEN EXIT END;
vi := gt.GetVisualInfo(pub,u.done); IF vi =NIL THEN EXIT END;
topborder := pub.wBorTop + pub.font.ySize + 1;
gad := gt.CreateContext(glist);
ng.textAttr := SYS.ADR(Topaz80);
ng.visualInfo := vi;
ng.userData := NIL;
ng.leftEdge := 16+100*0;
ng.topEdge := 90+topborder;
ng.width := 64;
ng.height := 12;
ng.gadgetText := SYS.ADR("Save");
ng.gadgetID := gadBUTTONSave;
ng.flags := LONGSET{};
gad := gt.CreateGadget(gt.buttonKind, gad, ng, u.done);
ng.leftEdge := 16+100*1;
ng.gadgetText := SYS.ADR("Use");
ng.gadgetID := gadBUTTONUse;
gad := gt.CreateGadget(gt.buttonKind, gad, ng, u.done);
ng.leftEdge := 16+100*2;
ng.gadgetText := SYS.ADR("Cancel");
ng.gadgetID := gadBUTTONCancel;
gad := gt.CreateGadget(gt.buttonKind, gad, ng, u.done);
lvlist.head := SYS.ADR(lvlist.tail);
lvlist.tail := NIL;
lvlist.tailPred := SYS.ADR(lvlist.head);
index := 0;
firstindex := -1;
dispID := g.NextDisplayInfo(g.invalidID);
WHILE dispID # g.invalidID DO
IF (g.GetDisplayInfoData(NIL,displayInfo,SIZE(displayInfo),g.dtagDisp,dispID) > 0) &
(displayInfo.notAvailable = 0) &
(LONGSET{g.isHAM,g.isExtraHalfBrite,g.isDualPF} * displayInfo.propertyFlags = LONGSET{}) &
(g.GetDisplayInfoData(NIL,nameInfo,SIZE(nameInfo),g.dtagName,dispID) > 0)
THEN
SYS.ALLOCATE(node);
IF node # NIL THEN
SYS.ALLOCATE(node.node.name);
IF node.node.name # NIL THEN
COPY(nameInfo.name,node.node.name^);
node.displayID := dispID;
e.AddTail(lvlist, node);
IF dispID=displayID THEN firstindex := index END;
INC(index);
ELSE
EXIT
END;
ELSE
EXIT
END;
END;
dispID := g.NextDisplayInfo(dispID);
END;
ng.leftEdge := 16;
ng.topEdge := 16+topborder;
ng.width := 265;
ng.height := 66;
ng.gadgetText := SYS.ADR("Choose Display Mode:");
ng.gadgetID := gadLISTVIEW;
ng.flags := LONGSET{gt.highLabel,gt.placeTextAbove};
IF firstindex >= 0 THEN lvSelectedTag := gt.lvSelected
ELSE lvSelectedTag := u.ignore END;
gad := gt.CreateGadget(gt.listViewKind, gad, ng,
gt.lvLabels, SYS.ADR(lvlist),
gt.lvShowSelected, NIL,
I.layoutaSpacing, 2,
lvSelectedTag, firstindex,
u.done);
IF gad = NIL THEN EXIT END;
win := I.OpenWindowTagsA(NIL,
I.waLeft, 0,
I.waTop, 8,
I.waInnerWidth, 290,
I.waInnerHeight, 106,
I.waTitle, SYS.ADR(MuchText),
I.waFlags, LONGSET{I.activate,I.windowDrag,I.windowDepth,I.simpleRefresh,I.rmbTrap},
I.waIDCMP, gt.listViewIDCMP+gt.buttonIDCMP+LONGSET{I.gadgetUp,I.refreshWindow},
I.waCustomScreen,pub,
I.waGadgets, glist,
u.done);
IF win = NIL THEN EXIT END;
gt.RefreshWindow(win, NIL);
dispID := displayID;
terminated := f;
WHILE ~terminated DO
e.WaitPort(win.userPort);
LOOP
IF terminated THEN EXIT END;
imsg := gt.GetIMsg(win.userPort);
IF imsg=NIL THEN EXIT END;
gad := imsg.iAddress;
IF I.gadgetUp IN imsg.class THEN
CASE gad.gadgetID OF
| gadBUTTONSave: result := 1; displayID := dispID; terminated := w;
| gadBUTTONUse: result := 2; displayID := dispID; terminated := w;
| gadBUTTONCancel: terminated := w;
| gadLISTVIEW: node := GetNode(lvlist,imsg.code);
IF node # NIL THEN dispID := node.displayID END;
ELSE
END;
END;
IF I.refreshWindow IN imsg.class THEN
gt.BeginRefresh(win);
gt.EndRefresh(win, I.LTRUE);
END;
gt.ReplyIMsg(imsg);
END;
END;
EXIT
END;
IF win # NIL THEN I.CloseWindow(win) END;
IF glist # NIL THEN gt.FreeGadgets(glist) END;
IF vi # NIL THEN gt.FreeVisualInfo(vi) END;
IF pub # NIL THEN I.UnlockPubScreen(NIL,pub) END;
RETURN result;
END ScreenModeReq;
(*-------------------------------------------------------------------------*)
PROCEDURE SavePrefs;
VAR
lock: d.FileLockPtr;
PROCEDURE SavePrefsName(name: StringPtr);
VAR file: d.FileHandlePtr;
l: LONGINT;
BEGIN
file := d.Open(name^,d.newFile);
IF file # NIL THEN
SYS.SETREG(0,d.Write(file,"FORM",4));
l := 16;
SYS.SETREG(0,d.Write(file,l,4));
SYS.SETREG(0,d.Write(file,"MUMO",4));
SYS.SETREG(0,d.Write(file,"DPID",4));
l := 4;
SYS.SETREG(0,d.Write(file,l,4));
SYS.SETREG(0,d.Write(file,id,4));
d.OldClose(file);
END;
END SavePrefsName;
BEGIN
IF DirExists("ENV:") THEN
IF ~DirExists("ENV:MuchMore") THEN
lock := d.CreateDir("ENV:MuchMore");
IF lock#NIL THEN d.UnLock(lock) END;
END;
SavePrefsName(SYS.ADR("ENV:MuchMore/MuchMore.prefs"))
END;
IF DirExists("ENVARC:") THEN
IF ~DirExists("ENVARC:MuchMore") THEN
lock := d.CreateDir("ENVARC:MuchMore");
IF lock#NIL THEN d.UnLock(lock) END;
END;
SavePrefsName(SYS.ADR("ENVARC:MuchMore/MuchMore.prefs"))
END;
END SavePrefs;
(*-------------------------------------------------------------------------*)
PROCEDURE LoadPrefs;
VAR file: d.FileHandlePtr;
l,i,s: LONGINT;
ok: BOOLEAN;
BEGIN
file := NIL;
IF DirExists("PROGDIR:") THEN
file := d.Open("PROGDIR:MuchMore.prefs",d.oldFile);
END;
IF (file=NIL) & DirExists("ENV:") THEN
file := d.Open("ENV:MuchMore/MuchMore.prefs",d.oldFile);
END;
IF file # NIL THEN
LOOP
IF (d.Read(file,i,4) <= 0) OR
(i # SYS.VAL(LONGINT,"FORM")) OR
(d.Read(file,s,4) <= 0) OR
(d.Read(file,i,4) <= 0) OR
(i # SYS.VAL(LONGINT,"MUMO")) THEN EXIT END;
WHILE w DO
IF (d.Read(file,i,4) <= 0) OR
(d.Read(file,s,4) <= 0) THEN EXIT END;
IF ODD(s) THEN INC(s) END;
IF (s=4) & (i=SYS.VAL(LONGINT,"DPID")) THEN
SYS.SETREG(0,d.Read(file,id,4));
ELSE
IF s < 0 THEN EXIT END;
SYS.SETREG(0,d.Seek(file,s,d.current));
END;
END;
EXIT;
END;
d.OldClose(file);
END;
END LoadPrefs;
(*------------------------ Get Tooltypes: --------------------------*)
PROCEDURE EvalIcon(icon: DiskObjectPtr);
VAR tt: StringPtr;
BEGIN
IF icon # NIL THEN
tt := FindToolType(icon.toolTypes,"COLORS"); IF (tt # NIL) THEN COPY(tt^,Pens) END;
tt := FindToolType(icon.toolTypes,"EXTRASPACE"); IF (tt # NIL) THEN spacing := SHORT(StrToInt(tt,10)) END;
tt := FindToolType(icon.toolTypes,"FONT"); IF (tt # NIL) THEN COPY(tt^,FontName) END;
tt := FindToolType(icon.toolTypes,"NOOSCAN"); IF (tt # NIL) & (MatchToolValue(tt^,"TRUE")) THEN noOscan := w END;
tt := FindToolType(icon.toolTypes,"ONEPLANE"); IF (tt # NIL) & (MatchToolValue(tt^,"TRUE")) THEN onePlane := w END;
tt := FindToolType(icon.toolTypes,"PASSWORD"); IF (tt # NIL) THEN COPY(tt^,Password) END;
tt := FindToolType(icon.toolTypes,"SCROLLMODE"); IF (tt # NIL) THEN scrollmode := SHORT(StrToInt(tt,10)) END;
tt := FindToolType(icon.toolTypes,"TABWIDTH"); IF (tt # NIL) THEN tabw := SHORT(StrToInt(tt,10)) END;
tt := FindToolType(icon.toolTypes,"TOGGLELACE"); IF (tt # NIL) & (MatchToolValue(tt^,"TRUE")) THEN lace := ~lace END;
tt := FindToolType(icon.toolTypes,"TOOLPRI"); IF (tt # NIL) THEN taskpri := SHORT(SHORT(StrToInt(tt,10))) END;
FreeDiskObject(icon);
END;
END EvalIcon;
(*------------------------------ MAIN: ----------------------------------*)
BEGIN
(*------ Init: ------*)
ol.OutOfMemHandler := OutOfMemHandler;
mySigBit := -1; Me := SYS.VAL(d.ProcessPtr,ol.Me);
WriteName := "PRT:"; MemIndex := ChunkSize; OldDir := Me.currentDir;
oldpri := Me.task.node.pri;
taskpri := oldpri;
Sync := w;
FontSize := 8;
Pattern := "~(#?.info)";
id := g.invalidID;
tabw := 8;
IF g.gfx.libNode.version >= 37 THEN scrollmode := 1 END;
I.GetPrefs(Prefs,SIZE(Prefs));
lace := Prefs.laceWB # SHORTSET{};
mySigBit := e.AllocSignal(-1);
IF mySigBit<0 THEN HALT(0) END;
mySig := LONGSET{mySigBit};
iconBase := e.OpenLibrary("icon.library",33);
(*------ Setup: ------*)
NEW(FirstLine);
(*FirstLine.size := 0;
FirstLine.text[0] := 0X; *)
(*------ Start: ------*)
LoadPrefs;
IF ol.wbStarted THEN
wbm := ol.wbenchMsg;
IF iconBase # NIL THEN
oldLace:=lace;
j := SHORT(wbm.numArgs); IF j>2 THEN j := 2 END;
FOR i := 0 TO j-1 DO
lace := oldLace;
SYS.SETREG(0,d.CurrentDir(wbm.argList[i].lock));
nameptr := wbm.argList[i].name;
icon := GetDiskObject(nameptr^);
IF (icon=NIL) & (d.base.lib.version >= 37) THEN
SYS.SETREG(0,d.CurrentDir(d.GetProgramDir()));
icon := GetDiskObject(nameptr^);
END;
EvalIcon(icon);
END;
END; (* IF iconBase#NIL *)
IF wbm.numArgs >= 2 THEN
ArgPtr := wbm.argList^[1].name; Name := ArgPtr^;
SYS.SETREG(0,d.CurrentDir(wbm.argList^[1].lock));
ELSE
SYS.SETREG(0,d.CurrentDir(wbm.argList^[0].lock));
FileReq(Name)
END;
ELSE
IF d.dos.lib.version < 37 THEN
IF ol.dosCmdLen > 1 THEN
CommLine := ol.dosCmdBuf;
j := 0;
LOOP
i := 0;
WHILE CommLine[j]=20X DO INC(j) END;
IF CommLine[j]=0AX THEN EXIT END;
IF CommLine[j]='"' THEN
INC(j);
LOOP
CASE CommLine[j] OF
| '"': INC(j); EXIT
| 0AX: EXIT
ELSE
option[i] := CommLine[j]; INC(i); INC(j);
END;
END;
ELSE
WHILE (CommLine[j]#0AX) & (CommLine[j]#20X) DO
option[i] := CommLine[j]; INC(i); INC(j);
END;
END;
option[i]:= 0X;
IF option="?" THEN Request(usage) END;
IF option[0]="-" THEN
CASE CAP(option[1]) OF
"A": tabw := SHORT(StrToInt(SYS.ADR(option[2]),10)) |
"C": GetStr(SYS.ADR(option[2]),Pens) |
"E": spacing := SHORT(StrToInt(SYS.ADR(option[2]),10)) |
"F": GetStr(SYS.ADR(option[2]),FontName) |
"L": lace := ~lace |
"O": onePlane := w |
"P": GetStr(SYS.ADR(option[2]),Password) |
"S": scrollmode := SHORT(StrToInt(SYS.ADR(option[2]),10)) |
"T": taskpri := SHORT(SHORT(StrToInt(SYS.ADR(option[2]),10))) |
ELSE
Request(usage);
END;
ELSE
COPY(option,Name);
END;
END;
END;
ELSE (* d.dos.lib.version >= 37 *)
IF iconBase#NIL THEN
oldcd := d.CurrentDir(d.GetProgramDir());
IF d.GetProgramName(Name,LEN(Name)) THEN
icon := GetDiskObject(Name);
EvalIcon(icon);
Name[0] := 0X;
END;
oldcd := d.CurrentDir(oldcd);
END;
rd := d.ReadArgs("A=TABWIDTH/N/K,C=COLORS/K,D=DISPMODEREQ/S,E=EXTRASPACE/N/K,F=FONT/K,N=NOOSCAN/S,O=ONEPLANE/S,P=PASSWORD/K,S=SCROLLMODE/N/K,T=TOOLPRI/N/K,FILE",args,NIL);
IF rd=NIL THEN
SYS.SETREG(0,d.PrintFault(d.IoErr(),NIL));
HALT(d.warn)
END;
IF args.a # NIL THEN tabw := SHORT(args.a^) END;
IF args.c # NIL THEN COPY(args.c^,Pens) END;
IF args.d # NIL THEN modeReq := w END;
IF args.e # NIL THEN spacing := SHORT(args.e^) END;
IF args.f # NIL THEN COPY(args.f^,FontName) END;
IF args.n # NIL THEN noOscan := w END;
IF args.o # NIL THEN onePlane := w END;
IF args.p # NIL THEN COPY(args.p^,Password) END;
IF args.s # NIL THEN scrollmode := SHORT(args.s^) END;
IF args.t # NIL THEN taskpri := SHORT(SHORT(args.t^)) END;
IF args.file # NIL THEN COPY(args.file^,Name) END;
d.FreeArgs(rd); rd := NIL;
END;
END;
IF tabw < 1 THEN tabw := 1 END;
IF taskpri#oldpri THEN SYS.SETREG(0,e.SetTaskPri(Me,taskpri)) END;
IF FontName[0]#0X THEN
i := 0;
j := SHORT(str.Length(FontName));
LOOP
IF i >= j THEN EXIT END;
IF FontName[i]='/' THEN
FontName[i] := 0X;
FontSize := SHORT(StrToInt(SYS.ADR(FontName[i+1]),10));
j := i;
EXIT
END;
INC(i);
END;
IF j<LEN(FontName)-6 THEN
e.CopyMem(".font",FontName[j],6);
END;
END;
IF FontSize>50 THEN FontSize := 50 END;
IF FontSize< 5 THEN FontSize := 5 END;
IF spacing< 0 THEN spacing := 0 END;
IF spacing>20 THEN spacing := 20 END;
IF modeReq & (gt.base#NIL) THEN
IF ScreenModeReq(id) = 1 THEN SavePrefs END;
END;
(*------ Open File: ------*)
LOOP
MyFile := d.Open(Name,d.oldFile);
IF MyFile#NIL THEN EXIT END;
FileReq(Name)
END;
(*------------------------ Open Display: --------------------------------*)
(*------ Open Screen: ------*)
IF lace THEN
NuScreen.viewModes := {g.hires,g.lace};
NuScreen.height := g.gfx.normalDisplayRows*2
ELSE
NuScreen.viewModes := {g.hires};
NuScreen.height := g.gfx.normalDisplayRows
END;
NuScreen.width := g.gfx.normalDisplayColumns;
NuScreen.depth := 2;
NuScreen.type := I.customScreen+{I.screenQuiet};
IF onePlane THEN NuScreen.depth := 1; END;
LOOP
IF I.int.libNode.version >= 37 THEN
IF id=g.invalidID THEN
id := g.defaultMonitorID;
pub := I.LockPubScreen("Workbench");
IF pub # NIL THEN
id := g.GetVPModeID(SYS.ADR(pub.viewPort));
I.UnlockPubScreen(NIL,pub);
END;
END;
IF g.GetDisplayInfoData(NIL,dims,SIZE(dims),g.dtagDims,id) > 0 THEN
IF noOscan THEN
NuScreen.width := dims.nominal.maxX - dims.nominal.minX + 1;
NuScreen.height := dims.nominal.maxY - dims.nominal.minY + 1;
overscanTag := u.ignore;
ELSE
NuScreen.width := dims.txtOScan.maxX - dims.txtOScan.minX + 1;
NuScreen.height := dims.txtOScan.maxY - dims.txtOScan.minY + 1;
overscanTag := I.saOverscan;
END;
IF g.GetDisplayInfoData(NIL,disp,SIZE(disp),g.dtagDisp,id) > 0 THEN
lace := g.isLace IN disp.propertyFlags;
Scrollable := (g.isDraggable IN disp.propertyFlags) (* & ((g.gfx.libNode.version<39) OR ~(20 IN disp.propertyFlags)) *);
IF scrollmode=3 THEN Scrollable := f END;
IF Scrollable THEN INC(NuScreen.height,NuScreen.height) END;
Screen := I.OpenScreenTags(NuScreen,
I.saDisplayID,id,
overscanTag,I.oScanText,
I.saPens,SYS.ADR("\xFF\xFF"),
(* saInterleaved,I.LFALSE, *)
u.end);
END;
END;
ELSE
Scrollable := w;
IF scrollmode=3 THEN Scrollable := f END;
IF Scrollable THEN INC(NuScreen.height,NuScreen.height) END;
Screen := I.OpenScreen(NuScreen);
END;
IF Screen#NIL THEN EXIT END;
DEC(NuScreen.depth);
IF NuScreen.depth=0 THEN Request(cos) END;
END;
IF NuScreen.depth=1 THEN onePlane := w END;
rp := SYS.ADR(Screen.rastPort);
BM := rp.bitMap;
IF Pens[0]#0X THEN
i := 0;
chptr := SYS.ADR(Pens);
Pens[LEN(Pens)-1] := 0X;
LOOP
Cols[i] := SHORT(StrToInt(SYS.VAL(StringPtr,chptr),16));
INC(i); IF i=4 THEN EXIT END;
WHILE (chptr^#0X) & (chptr^#",") DO
chptr:=SYS.VAL(e.APTR,SYS.VAL(LONGINT,chptr)+1)
END;
IF chptr^="," THEN
chptr:=SYS.VAL(e.APTR,SYS.VAL(LONGINT,chptr)+1)
ELSE
EXIT
END;
END;
g.LoadRGB4(SYS.ADR(Screen.viewPort),Cols,i);
END;
IF FontName[0]#0X THEN
MyAttr.name := SYS.ADR(FontName);
MyAttr.ySize := FontSize;
IF diskFontBase=NIL THEN diskFontBase := e.OpenLibrary("diskfont.library",33) END;
IF diskFontBase#NIL THEN MyFont := OpenDiskFont(MyAttr) END;
IF (MyFont#NIL) & ~(g.proportional IN MyFont.flags) THEN g.SetFont(rp,MyFont) END;
END;
LOOP
fontWidth := rp.font.xSize;
fontHeight := rp.font.ySize;
IF (fontWidth<=50) OR (fontHeight<=50) & (fontWidth>2) & (fontHeight>2) THEN EXIT END;
MyAttr.name := SYS.ADR("topaz.font");
MyAttr.ySize := 8;
MyFont := g.OpenFont(MyAttr);
IF MyFont=NIL THEN HALT(0) END;
g.SetFont(rp,MyFont);
END;
INC(fontHeight,spacing); (* extra spacing *)
fontBaseLine := rp.font.baseline;
NumColumns := Screen.width DIV fontWidth;
IF Scrollable THEN NumLines := Screen.height DIV 2 DIV fontHeight;
ELSE NumLines := Screen.height DIV fontHeight; END;
LineSize := LONG(fontHeight)*BM.bytesPerRow;
PageSize := LineSize*NumLines;
PageHeight := fontHeight*NumLines;
NuScreen.height := fontHeight*NumLines;
NuScreen.width := Screen.width;
IF Scrollable THEN
(*
IF NuScreen.depth=1 THEN BM.planes[1] := BM.planes[0] END;
*)
ri := Screen.viewPort.rasInfo;
ClearBitMaps;
ri.ryOffset := 32;
Screen.height := NuScreen.height;
I.MakeScreen(Screen);
I.RethinkDisplay;
END;
(*------ Open Window: ------*)
NuWindow.flags := LONGSET{I.rmbTrap,I.activate,I.borderless};
NuWindow.screen := Screen;
NuWindow.type := I.customScreen;
NuWindow.topEdge:= 10;
NuWindow.width := Screen.width;
NuWindow.height := Screen.height-10;
NuWindow.idcmpFlags := MyIdcmp;
Window := I.OpenWindow(NuWindow);
IF Window=NIL THEN Request(cow) END;
ClearBitMaps;
(*------ Get KeyMap: ------*)
IF e.OpenDevice("console.device",-1,SYS.ADR(wreq),LONGSET{})#0 THEN Request(conerr) END;
console := wreq.device;
(*ievent.nextEvent := NIL;
ievent.qualifier := {};
ievent.eventAddress := NIL; *)
ievent.class := ie.rawkey;
FOR i := 0 TO 3FH DO
ievent.code := i;
RawKeyConvert(SYS.ADR(ievent),SYS.ADR(KeyMap[i]),10H,NIL);
END;
(*------ Decrunch: ------*)
Decrunch;
(*------ Init 2nd Task: ------*)
ShowTask.spLower := SYS.ADR(ShowStack);
ShowTask.spUpper := SYS.ADR(ShowStack[1000]);
ShowTask.spReg := ShowTask.spUpper;
ShowTask.node.type := e.task;
ShowTask.node.name := SYS.ADR("Show.MM");
ShowTask.node.pri := Me.task.node.pri+1;
(* $IF SmallData *)
ShowTask.userData := SYS.REG(13); (* VarBase *)
(* $END *)
e.Forbid;
e.AddTask(SYS.ADR(ShowTask),ShowProc,NIL);
ShowTaskRunning := w;
Window.userPort.sigTask := SYS.ADR(ShowTask);
e.Permit;
(*------ Main Load / Display Loop: ------*)
LOOP
fg := 1; bg := 0; style := SHORTSET{};
RQLen := -1; RQPos := -1;
AnzLines := 1;
LastLine := FirstLine;
BottomLine := FirstLine;
TopLine := FirstLine;
TextLength := 0;
FindLine := NIL;
FOR i := 0 TO 9 DO TextMarkers[i] := NIL END;
MyLock := d.Lock(Name,d.sharedLock);
IF MyLock=NIL THEN Request(cof) END;
IF ~ d.Examine(MyLock,FileInfo) THEN Request(cof) END;
FileLength := FileInfo.size;
d.UnLock(MyLock); MyLock := NIL;
IF FileLength=0 THEN Request("File empty") END;
(*------ Start displaying & Loading: ------*)
NewDisp := w;
e.Signal(SYS.ADR(ShowTask),mySig);
REPEAT
LoadLine := GetTextLine();
IF LoadLine=NIL THEN
d.OldClose(MyFile);
MyFile := NIL;
ELSE
LoadLine.prev := LastLine;
LastLine.next := LoadLine;
LastLine := LoadLine;
END;
IF SignalNewData THEN e.Signal(SYS.ADR(ShowTask),mySig) END;
UNTIL (MyFile=NIL) OR Done OR NewText;
IF SignalAllRead THEN e.Signal(SYS.ADR(ShowTask),mySig) END;
REPEAT
SYS.SETREG(0,e.Wait(mySig));
IF print THEN
in := d.Open("NIL:",d.oldFile); out := d.Open("NIL:",d.newFile);
SYS.SETREG(0,d.Execute(PStr,in,out));
d.OldClose(in); in := NIL; d.OldClose(out); out := NIL; print := f;
END;
IF save THEN
in := d.Open(Name,d.oldFile);
IF in=NIL THEN I.DisplayBeep(NIL) ELSE
ol.New(buffer,savesize);
SYS.SETREG(0,d.Seek(in,savefrom,0));
IF d.Read(in,buffer^,savesize)#savesize THEN
I.DisplayBeep(NIL); d.OldClose(in); in := NIL;
ELSE
d.OldClose(in); in := NIL;
out := d.Open(WriteName,d.newFile);
IF out=NIL THEN I.DisplayBeep(NIL) ELSE
IF d.Write(out,buffer^,savesize)#savesize THEN I.DisplayBeep(NIL) END;
d.OldClose(out); out := NIL;
END;
END;
DISPOSE(buffer);
END;
save := f;
END;
IF Done THEN EXIT END;
UNTIL NewText;
IF MyFile#NIL THEN d.OldClose(MyFile); MyFile := NIL END;
IF Decrunched & d.DeleteFile(Name) THEN END;
Decrunched := f;
DisposeLines();
FirstLine^.next := NIL; NewText := f;
Name := OldName;
REPEAT
FileReq(Name);
MyFile := d.Open(Name,d.oldFile);
UNTIL MyFile#NIL;
Decrunch;
END; (* LOOP *)
CLOSE
IF win #NIL THEN I.CloseWindow(win) END;
IF ShowTaskRunning THEN e.RemTask(SYS.ADR(ShowTask)) END;
IF console #NIL THEN e.CloseDevice(SYS.ADR(wreq)) END;
IF Window #NIL THEN I.CloseWindow(Window) END;
IF Screen #NIL THEN d.Delay(2); I.OldCloseScreen(Screen) END;
IF MyFont #NIL THEN g.CloseFont(MyFont) END;
IF MyFile #NIL THEN d.OldClose(MyFile) END;
IF in #NIL THEN d.OldClose(in) END;
IF out #NIL THEN d.OldClose(out) END;
IF Decrunched THEN SYS.SETREG(0,d.DeleteFile(Name)) END;
IF MyLock #NIL THEN d.UnLock(MyLock) END;
IF xpk #NIL THEN e.CloseLibrary(xpk) END;
IF arp #NIL THEN e.CloseLibrary(arp) END;
IF asl #NIL THEN e.CloseLibrary(asl) END;
IF diskFontBase#NIL THEN e.CloseLibrary(diskFontBase) END;
IF iconBase #NIL THEN e.CloseLibrary(iconBase) END;
IF rd #NIL THEN d.FreeArgs(rd) END;
IF mySigBit>=0 THEN e.FreeSignal(mySigBit) END;
IF taskpri #oldpri THEN oldpri := e.SetTaskPri(Me,oldpri) END;
OldDir := d.CurrentDir(OldDir);
END MuchMore.